﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


public partial class colGridView : DataGridView
{
    public colGridView()
    {
        InitializeComponent();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }
    private enum BindType
    {
        initialize,
        filter
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="gvr"></param>
    public delegate void RowDataBinded(DataGridViewRow gvr);
    [Description("数据绑定时发生，返回已经绑定到列表中的行"), Category("行为")]
    public event RowDataBinded RowDataBinding;
    [Description("双击数据行任意位置时发生，返回双击的数据行"), Category("鼠标")]
    public event RowDataBinded RowDoubleClick;
    private Dictionary<int, ComboBox> _combdict = new Dictionary<int, ComboBox>();
    private Dictionary<int, string> _filter = new Dictionary<int, string>();
    private object _datasource = null;
    public new object DataSource
    {
        get { return _datasource; }
        set { _datasource = value; DataBind(); }
    }
    /// <summary>
    /// 添加列
    /// </summary>
    /// <param name="colType"></param>
    /// <param name="headerText"></param>
    /// <param name="dataPropertyName"></param>
    /// <param name="width">-1为自动填充，0位不显示，其他值按照实际宽度显示</param>
    public void AddColumn(Type colType, string headerText, string dataPropertyName, int width = -1, bool headerDropDown = false)
    {
        //设置GridViewHeadr为高度可编辑
        if (ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.DisableResizing)
            ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
        DataGridViewColumn col = Activator.CreateInstance(colType, true) as DataGridViewColumn;
        if (col != null)
        {
            //设置列
            col.Name = dataPropertyName;
            col.DataPropertyName = dataPropertyName;
            col.HeaderText = headerText;
            if (width == -1) col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            else if (width == 0) col.Visible = false;
            else col.Width = width;
            Columns.Add(col);
            //如果列Header需要显示ComboBox
            if (headerDropDown)
            {
                ComboBox combo = new ComboBox();
                Rectangle rt = GetCellDisplayRectangle(col.Index, -1, false);
                int cellX = GetCellDisplayRectangle(col.Index, -1, false).X + 1;
                int cellY = GetCellDisplayRectangle(col.Index, -1, false).Y + 1;
                combo.Tag = col.Index;
                combo.DropDownStyle = ComboBoxStyle.DropDownList;
                //置顶
                combo.BringToFront();
                //设置ComboBox显示样式
                combo.FlatStyle = FlatStyle.Flat;
                //设置ComboBox大小
                combo.Size = new Size(rt.Width - 2, rt.Height);
                //设置ComboBox显示文职
                combo.Location = new Point(cellX, cellY);
                //添加ComboBox下拉选择事件
                combo.SelectedIndexChanged += new EventHandler(colHeaderCellCombo_SelectIndexChanged);
                this.Controls.Add(combo);
                //根据ComboBox的高度调整Header高度
                ColumnHeadersHeight = combo.Size.Height + 2;
                _combdict.Add(col.Index, combo);
                combo.Items.Add(headerText);
                combo.SelectedIndex = 0;
            }
        }
    }
    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="item"></param>
    public void AddItem(object item, int rowindex = 0)
    {
        DataGridViewRow dvr = new DataGridViewRow();
        dvr.CreateCells(this);
        Type ty = item.GetType();
        if (ty.Name == "DataRow")
        {
            DataRow dr = item as DataRow;
            foreach (DataGridViewColumn gvc in Columns)
            {
                if (dr.Table.Columns.Contains(gvc.DataPropertyName))
                {
                    dvr.Cells[gvc.Index].Value = dr[gvc.DataPropertyName].ToString();
                }
            }
            DataTable dt = _datasource as DataTable;
            if (dt == null) dt = dr.Table;
            dt.Rows.Add(item as DataRow);
            _datasource = dt;
        }
        else
        {
            foreach (DataGridViewColumn gvc in Columns)
            {
                Type obj_t = item.GetType();
                var fInfo = obj_t.GetField(gvc.DataPropertyName);
                if (fInfo != null)
                {
                    dvr.Cells[gvc.Index].Value = fInfo.GetValue(item).ToString();
                }
            }
            IList ilist = (IList)_datasource;
            if (ilist == null) ilist = new List<object>();
            ilist.Add(item);
            _datasource = ilist;

        }
        this.Rows.Insert(rowindex, dvr);
        if (RowDataBinding != null)
            RowDataBinding(dvr);
    }
    /// <summary>
    /// 获取选中的行
    /// </summary>
    /// <returns></returns>
    public List<DataGridViewRow> GetSelected()
    {
        int colIndex = -1;
        foreach (DataGridViewColumn gvc in Columns)
        {
            if (gvc.GetType().Name == "DataGridViewCheckBoxColumn") colIndex = gvc.Index;
        }
        if (colIndex != -1)
        {
            List<DataGridViewRow> rowList = new List<DataGridViewRow>();
            foreach (DataGridViewRow row in Rows)
            {
                DataGridViewCheckBoxCell cbc = row.Cells[colIndex] as DataGridViewCheckBoxCell;
                if (cbc.Value != null && cbc.Value.ToString() == "true")
                    rowList.Add(row);
            }
            return rowList;
        }
        return null;
    }
    /// <summary>
    /// 绑定数据
    /// </summary>
    private void DataBind(BindType bt = BindType.initialize)
    {
        this.Rows.Clear();
        if (_datasource == null) return;
        Type ty = _datasource.GetType();
        if (ty.Name == "DataTable")
        {
            DataTable dt = _datasource as DataTable;
            foreach (DataRow dr in dt.Rows)
            {
                DataGridViewRow dvr = new DataGridViewRow();
                dvr.CreateCells(this);
                int number_index = -1;
                foreach (DataGridViewColumn gvc in Columns)
                {
                    if (gvc.HeaderText == "序号")
                    {
                        number_index = gvc.Index;
                    }
                    else if (dr.Table.Columns.Contains(gvc.DataPropertyName))
                    {
                        dvr.Cells[gvc.Index].Value = dr[gvc.DataPropertyName].ToString();
                        if (bt == BindType.initialize)
                            AddComboHeaderItem(gvc.Index, dvr.Cells[gvc.Index].Value.ToString());
                    }
                }
                if (IsFilter(dvr))
                {
                    this.Rows.Add(dvr);
                    if (number_index != -1) dvr.Cells[number_index].Value = dvr.Index + 1;
                }

                if (RowDataBinding != null)
                    RowDataBinding(dvr);
            }
        }
        else if (ty.Name == "List`1")
        {
            IList lt = _datasource as IList;
            foreach (var obj in lt)
            {
                DataGridViewRow dvr = new DataGridViewRow();
                dvr.CreateCells(this);
                int number_index = -1;
                foreach (DataGridViewColumn gvc in Columns)
                {
                    if (gvc.HeaderText == "序号")
                    {
                        number_index = gvc.Index;
                    }
                    else
                    {
                        Type obj_t = obj.GetType();
                        var fInfo = obj_t.GetField(gvc.DataPropertyName);
                        if (fInfo != null)
                        {
                            dvr.Cells[gvc.Index].Value = fInfo.GetValue(obj).ToString();
                            if (bt == BindType.initialize)
                                AddComboHeaderItem(gvc.Index, dvr.Cells[gvc.Index].Value.ToString());
                        }
                    }
                }
                if (IsFilter(dvr))
                {
                    this.Rows.Add(dvr);
                    if (number_index != -1) dvr.Cells[number_index].Value = dvr.Index + 1;
                }
                if (RowDataBinding != null)
                    RowDataBinding(dvr);
            }
        }
    }
    /// <summary>
    /// comboheader添加项
    /// </summary>
    /// <param name="comb"></param>
    /// <param name="itemtext"></param>
    private void AddComboHeaderItem(int colIndex, string itemtext)
    {
        if (_combdict.ContainsKey(colIndex))
        {
            bool flag = true;
            ComboBox comb = _combdict[colIndex];
            foreach (var item in comb.Items)
            {
                if (item.ToString() == itemtext)
                {
                    flag = false;
                    break;
                }
            }
            if (flag)
                comb.Items.Add(itemtext);
        }

    }
    /// <summary>
    /// 刷新GridViewHeader
    /// </summary>
    private void RefComboHeader()
    {
        foreach (var item in _combdict)
        {
            Rectangle rt = GetCellDisplayRectangle(item.Key, -1, false);
            int cellX = GetCellDisplayRectangle(item.Key, -1, false).X + 1;
            int cellY = GetCellDisplayRectangle(item.Key, -1, false).Y + 1;
            DataGridViewColumn gvc = Columns[item.Key];
            //item.Value.Text = gvc.HeaderText;
            item.Value.BringToFront();
            //item.Value.FlatStyle = FlatStyle.Flat;
            item.Value.Size = new Size(rt.Width - 2, rt.Height);
            item.Value.Location = new Point(cellX, cellY);
            ColumnHeadersHeight = item.Value.Size.Height + 2;
        }
    }
    /// <summary>
    /// 双击单元格事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void colGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
    {
        if (RowDoubleClick != null && e.RowIndex != -1)
            RowDoubleClick(this.Rows[e.RowIndex]);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void colGridView_CellClick(object sender, DataGridViewCellEventArgs e)
    {
        Type ty = this.Columns[e.ColumnIndex].GetType();
        if (ty.Name == "DataGridViewCheckBoxColumn")
        {
            if (e.RowIndex == -1)
            {
                foreach (DataGridViewRow row in Rows)
                {
                    DataGridViewCheckBoxCell cbc = row.Cells[e.ColumnIndex] as DataGridViewCheckBoxCell;
                    cbc.Value = (cbc.Value == null || cbc.Value.ToString() == "false") ? "true" : "false";
                }
            }
            else
            {
                DataGridViewCheckBoxCell cbc = this.Rows[e.RowIndex].Cells[e.ColumnIndex] as DataGridViewCheckBoxCell;
                cbc.Value = (cbc.Value == null || cbc.Value.ToString() == "false") ? "true" : "false";
            }
        }
    }
    /// <summary>
    /// 加载数据是否过滤
    /// </summary>
    /// <param name="dvr"></param>
    /// <returns></returns>
    private bool IsFilter(DataGridViewRow dvr)
    {
        if (_filter.Count == 0) return true;
        foreach (var item in _filter)
        {
            if (dvr.Cells[item.Key].Value.ToString() != item.Value.ToString())
                return false;
        }
        return true;
    }
    /// <summary>
    /// HeaderComboBox下拉选择事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void colHeaderCellCombo_SelectIndexChanged(object sender, EventArgs e)
    {
        ComboBox comb = sender as ComboBox;
        if (comb.SelectedIndex == 0)
        {
            _filter.Remove(Convert.ToInt32(comb.Tag));
        }
        else
        {
            _filter[Convert.ToInt32(comb.Tag)] = comb.Text;
        }
        DataBind(BindType.filter);
    }
    /// <summary>
    /// 出现滚动条后，拖动滚动条刷新Header
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void colGridView_Scroll(object sender, ScrollEventArgs e)
    {
        RefComboHeader();
    }

    private void colGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
    {
        RefComboHeader();
    }
}

